/*

 */
package com.ohos.connent.bizscenecloud.biz.modular.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ohos.connent.bizscenecloud.biz.modular.device.entity.BusinessDevLibFile;
import com.ohos.connent.bizscenecloud.biz.modular.device.enums.BizDeviceFileTypeEnum;
import com.ohos.connent.bizscenecloud.biz.modular.device.mapper.BizDeviceMapper;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDeviceAddParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDeviceEditParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDeviceIdParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDeviceIdsParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDevicePageParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.param.BizDeviceUploadParam;
import com.ohos.connent.bizscenecloud.biz.modular.device.result.BizDeviceUploadAuthResult;
import com.ohos.connent.bizscenecloud.biz.modular.device.service.BizDeviceService;
import com.ohos.connent.bizscenecloud.common.cache.CommonCacheOperator;
import com.ohos.connent.bizscenecloud.common.enums.CommonSortOrderEnum;
import com.ohos.connent.bizscenecloud.common.exception.CommonException;
import com.ohos.connent.bizscenecloud.common.page.CommonPageRequest;
import com.ohos.connent.bizscenecloud.dev.api.DevFileApi;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import javax.annotation.Resource;


/**
 * 设备端Service接口实现类
 **/
@Slf4j
@Service
public class BizDeviceServiceImpl extends ServiceImpl<BizDeviceMapper, BusinessDevLibFile> implements BizDeviceService {

    private static final String DEV_FILE_HWYUN_AUTH_URL_CACHE_KEY = "dev-file:BIZ_SCENE_HUAWEI_YUN_AUTH_URL:";

    private static final String REG_EXP_PATTERN_DEVICE_LIBRARY_VERSION = "^\\d+(\\.\\d+){3}$";

    private static final Map<String, Map<String, String>> ICON_CACHE_MAP = new ConcurrentHashMap<>();

    @Resource
    DevFileApi devFileApi;

    @Resource
    CommonCacheOperator commonCacheOperator;

    @Override
    public Page<BusinessDevLibFile> page(BizDevicePageParam bizDevicePageParam) {
        QueryWrapper<BusinessDevLibFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(BusinessDevLibFile::getId, BusinessDevLibFile::getFileId, BusinessDevLibFile::getLibVersion, BusinessDevLibFile::getFileType,
                        BusinessDevLibFile::getName, BusinessDevLibFile::getDescription, BusinessDevLibFile::getSizeB, BusinessDevLibFile::getCreateTime,BusinessDevLibFile::getFileName);
        if (ObjectUtil.isNotEmpty(bizDevicePageParam.getSearchKey())) {
            queryWrapper.lambda().like(BusinessDevLibFile::getName, bizDevicePageParam.getSearchKey());
        }
        if (ObjectUtil.isAllNotEmpty(bizDevicePageParam.getSortField(), bizDevicePageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(bizDevicePageParam.getSortOrder());

            queryWrapper.orderBy(true, bizDevicePageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(bizDevicePageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByDesc(BusinessDevLibFile::getCreateTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper.lambda().eq(BusinessDevLibFile::getFileType, BizDeviceFileTypeEnum.DEVICE.getValue()));
    }

    @Override
    public BizDeviceUploadAuthResult getHWYunUploadAuthUrlAndFileId(BizDeviceUploadParam bizDeviceUploadParam) {
        String fileId = devFileApi.getFileUploadAuthUrlHUAWEI(bizDeviceUploadParam.getFileName(), bizDeviceUploadParam.getTimeoutSeconds());
        String url = (String) commonCacheOperator.get(DEV_FILE_HWYUN_AUTH_URL_CACHE_KEY + fileId);
        if (ObjectUtil.isEmpty(url)) {
            throw new CommonException("文件路径不存在或已过期");
        }

        return new BizDeviceUploadAuthResult().setFileId(fileId).setUrl(url);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(BizDeviceAddParam bizDeviceAddParam) {
        checkAddParam(bizDeviceAddParam);
        BusinessDevLibFile businessDevLibFile = BeanUtil.toBean(bizDeviceAddParam, BusinessDevLibFile.class);
        businessDevLibFile.setId(IdWorker.getIdStr())
                .setLibVersion(bizDeviceAddParam.getDevlibVersion())
                .setFileType(BizDeviceFileTypeEnum.DEVICE.getValue());
        this.save(businessDevLibFile);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(BizDeviceIdsParam bizDeviceIdsParam) {
        this.removeByIds(bizDeviceIdsParam.getIds());
    }

    @Override
    public String getFileDownloadAuthUrlHUAWEI(BizDeviceIdParam bizDeviceIdParam) {
        String url = devFileApi.getFileDownloadAuthUrlHUAWEI(bizDeviceIdParam.getId(), 3600L);
        if (ObjectUtil.isEmpty(url) || "没有相关文件".equals(url)) {
            throw new CommonException("无法获取文件下载路径");
        }
        return url;
    }

    @Override
    public void upload(MultipartFile file, String fileId) {
        devFileApi.storageFileHUAWEI(fileId, file);

        // 文件是否上传成功
        if (!devFileApi.isExistingFileHUAWEI(fileId)) {
            throw new CommonException("文件上传失败，请重传文件");
        }
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("fileId",  fileId);
        hashMap.put("fileSize",String.valueOf(file.getSize()));
        ICON_CACHE_MAP.put("fileDetail", hashMap);
    }

    @Override
    public BusinessDevLibFile detail(String deviceId) {
        BusinessDevLibFile businessDevLibFile = getById(deviceId);
        return businessDevLibFile;
    }

    @Override
    public void edit(BizDeviceEditParam bizDeviceEditParam) {
        checkEditParam(bizDeviceEditParam);
        String id = bizDeviceEditParam.getId();
        BusinessDevLibFile businessDevLibFile = this.getById(id);
        if (ObjectUtil.isEmpty(businessDevLibFile)){
            throw new CommonException("设备库不存在");
        }
        BusinessDevLibFile businessDevLibFileRes = BeanUtil.copyProperties(bizDeviceEditParam, BusinessDevLibFile.class);
        businessDevLibFileRes.setLibVersion(bizDeviceEditParam.getDevlibVersion()).setFileType(BizDeviceFileTypeEnum.DEVICE.getValue());
        this.updateById(businessDevLibFileRes);
    }

    private void checkAddParam(BizDeviceAddParam bizDeviceAddParam) {
        String fileId = bizDeviceAddParam.getFileId();
        if (!devFileApi.isExistingFileHUAWEI(fileId)) {
            throw new CommonException("文件上传失败，请重传文件");
        }
        String devlibVersion = bizDeviceAddParam.getDevlibVersion();
        if (!Pattern.matches(REG_EXP_PATTERN_DEVICE_LIBRARY_VERSION, devlibVersion)) {
            throw new CommonException("版本名称当前只支持形如1.1.1.1格式的数字组合");
        }
        boolean hasSameVersion = this.count(new QueryWrapper<BusinessDevLibFile>().lambda()
                .eq(BusinessDevLibFile::getLibVersion, devlibVersion)
                .eq(BusinessDevLibFile::getFileType, BizDeviceFileTypeEnum.DEVICE.getValue())) > 0;
        if (hasSameVersion) {
            throw new CommonException("已存在重复的版本名称：{}", devlibVersion);
        }
    }

    private void checkEditParam(BizDeviceEditParam bizDeviceEditParam) {
        String fileId = bizDeviceEditParam.getFileId();
        if (!devFileApi.isExistingFileHUAWEI(fileId)) {
            throw new CommonException("文件上传失败，请重传文件");
        }
        String devlibVersion = bizDeviceEditParam.getDevlibVersion();
        if (!Pattern.matches(REG_EXP_PATTERN_DEVICE_LIBRARY_VERSION, devlibVersion)) {
            throw new CommonException("版本名称当前只支持形如1.1.1.1格式的数字组合");
        }
        List<BusinessDevLibFile> list = this.list(new QueryWrapper<BusinessDevLibFile>().lambda()
                .eq(BusinessDevLibFile::getLibVersion, devlibVersion)
                .eq(BusinessDevLibFile::getFileType, BizDeviceFileTypeEnum.DEVICE.getValue()));
        for (BusinessDevLibFile businessDevLibFile : list) {
            if (!businessDevLibFile.getId().equals(bizDeviceEditParam.getId())) {
                throw new CommonException("已存在重复的版本名称：{}", devlibVersion);
            }
        }

    }
}
